﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;

namespace OAuthAccess
{
    /// <summary>
    /// Uses this class until Access Token is obtained.
    /// </summary>
    public static class OAuthAuthorizationService
    {
        /// <summary>
        /// Gets RequestToken without proxy.
        /// </summary>
        /// <param name="consumer">Consumer Information.</param>
        /// <param name="requestTokenUrl">The string of Request Token Url.</param>
        /// <param name="realm">The string of Realm.You can also specify Null.</param>
        /// <param name="type">HttpMethodType.Usually the parameter is POST. But the case of twitter is specified GET.</param>
        /// <returns>The Instance of TokenResponse.</returns>
        public static TokenResponse GetRequestToken(Consumer consumer, string requestTokenUrl, string realm, HttpMethodType type)
        {
            return GetRequestToken(consumer, requestTokenUrl, realm, type, null);
        }

        /// <summary>
        /// Gets RequestToken with proxy.
        /// </summary>
        /// <param name="consumer">Consumer Information.</param>
        /// <param name="requestTokenUrl">The string of Request Token Url.</param>
        /// <param name="realm">The string of Realm.You can also specify Null.</param>
        /// <param name="type">HttpMethodType.Usually the parameter is POST. But the case of twitter is specified GET.</param>
        /// <param name="proxy">proxy</param>
        /// <returns>The Instance of TokenResponse.</returns>
        public static TokenResponse GetRequestToken(Consumer consumer, string requestTokenUrl, string realm, HttpMethodType type, WebProxy proxy)
        {
            string authorizationHeader = OAuthUtility.GenerateAuthorizationHeader(
                realm,
                requestTokenUrl,
                type,
                consumer,
                null,
                null,
                new Parameter[] { });

            HttpWebRequest req = WebRequest.Create(requestTokenUrl) as HttpWebRequest;
            req.Headers["Authorization"] = authorizationHeader;

            if (proxy != null)
            {
                req.Proxy = proxy;
            }

            OAuthResponse res = new OAuthResponse(req.GetResponse() as HttpWebResponse);

            List<Parameter> parameters = res.ResponseText.ParseParameters();

            RequestToken requestToken = new RequestToken(
                parameters.Find(p => p.Key=="oauth_token").Value,
                parameters.Find(p => p.Key=="oauth_token_secret").Value
                );

            var additionalParameters = from p in parameters
                                       where (p.Key != "oauth_token") && (p.Key != "oauth_token_secret")
                                       select p;

            return new TokenResponse(requestToken, additionalParameters);
        }

        /// <summary>
        /// Gets the User Authorization Url by Request Token.
        /// </summary>
        /// <param name="url">The string of User Authorization Url.</param>
        /// <param name="rToken">The instance of Request Token.</param>
        /// <returns>The string of User Authorization Url.</returns>
        public static string GetUserAuthorizationURL(string url, RequestToken rToken)
        {
            return url + "?oauth_token=" + rToken.Token;
        }

        /// <summary>
        /// Gets the Access Token without proxy.
        /// </summary>
        /// <param name="consumer">Consumer Information.</param>
        /// <param name="accessTokenUrl">The string of Access Token Url.</param>
        /// <param name="realm">The string of Realm.You can also specify Null.</param>
        /// <param name="requestToken">The instance of Request Token.</param>
        /// <param name="verifier">The string of Verifier.(was inputted by user.)</param>
        /// <param name="type">HttpMethodType.Usually the parameter is POST.</param>
        /// <returns>The Instance of TokenResponse.</returns>
        public static TokenResponse GetAccessToken(Consumer consumer, string accessTokenUrl, string realm, RequestToken requestToken, string verifier, HttpMethodType type)
        {
            return GetAccessToken(consumer, accessTokenUrl, realm, requestToken, verifier, type, null);
        }

        /// <summary>
        /// Gets the Access Token with proxy.
        /// </summary>
        /// <param name="consumer">Consumer Information.</param>
        /// <param name="accessTokenUrl">The string of Access Token Url.</param>
        /// <param name="realm">The string of Realm.You can also specify Null.</param>
        /// <param name="requestToken">The instance of Request Token.</param>
        /// <param name="verifier">The string of Verifier.(was inputted by user.)</param>
        /// <param name="type">HttpMethodType.Usually the parameter is POST.</param>
        /// <param name="proxy">proxy</param>
        /// <returns>The Instance of TokenResponse.</returns>
        public static TokenResponse GetAccessToken(Consumer consumer, string accessTokenUrl,string realm,RequestToken requestToken,string verifier,HttpMethodType type,WebProxy proxy)
        {
            string authorizationHeader = OAuthUtility.GenerateAuthorizationHeader(
                realm,
                accessTokenUrl,
                type,
                consumer,
                requestToken,
                verifier,
                new Parameter[] { });

            HttpWebRequest req = WebRequest.Create(accessTokenUrl) as HttpWebRequest;
            req.Headers["Authorization"] = authorizationHeader;

            if (proxy != null)
            {
                req.Proxy = proxy;
            }

            OAuthResponse res = new OAuthResponse(req.GetResponse() as HttpWebResponse);

            List<Parameter> parameters = res.ResponseText.ParseParameters();

            AccessToken accessToken = new AccessToken(
                parameters.Find(p => p.Key == "oauth_token").Value,
                parameters.Find(p => p.Key == "oauth_token_secret").Value
                );

            var additionalParameters = from p in parameters
                                       where (p.Key != "oauth_token") && (p.Key != "oauth_token_secret")
                                       select p;

            return new TokenResponse(accessToken, additionalParameters);
        }
    }
}
